package com.houweishi.module.oaDimission.service.impl;

import com.alibaba.fastjson.JSON;
import com.houweishi.common.constant.Constants;
import com.houweishi.common.constant.HttpStatus;
import com.houweishi.common.core.domain.AjaxResult;
import com.houweishi.common.core.domain.entity.SysUser;
import com.houweishi.common.core.domain.model.LoginUser;
import com.houweishi.common.exception.base.BaseException;
import com.houweishi.common.utils.DateUtils;
import com.houweishi.common.utils.SecurityUtils;
import com.houweishi.module.bizSerialNum.service.IBizSerialNumTService;
import com.houweishi.module.copy.domain.BizCopy;
import com.houweishi.module.copy.mapper.BizCopyMapper;
import com.houweishi.module.oaDimission.domain.OaDimission;
import com.houweishi.module.oaDimission.mapper.OaDimissionMapper;
import com.houweishi.module.oaDimission.service.IOaDimissionService;
import com.houweishi.module.record.domain.BizApprovalRecord;
import com.houweishi.module.record.mapper.BizApprovalRecordMapper;
import com.houweishi.module.record.service.IBizApprovalRecordService;
import com.houweishi.module.staff.domain.BizStaff;
import com.houweishi.module.staff.mapper.BizStaffMapper;
import com.houweishi.module.syTableRecord.service.ISyTableRecordTService;
import com.houweishi.system.mapper.SysUserMapper;
import com.houweishi.ws.po.Message;
import com.houweishi.ws.service.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 离职申请Service业务层处理
 * 
 * @author houweishi
 * @date 2023-07-19
 */
@Service
public class OaDimissionServiceImpl implements IOaDimissionService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(OaDimissionServiceImpl.class);
    @Resource
    private OaDimissionMapper oaDimissionMapper;

    /**
     * 生成单号Service
     */
    @Resource
    private IBizSerialNumTService iBizSerialNumTService;

    /**
     * 审批Mapper
     */
    @Resource
    private BizApprovalRecordMapper bizApprovalRecordMapper;

    /**
     * 抄送Mapper
     */
    @Resource
    private BizCopyMapper bizCopyMapper;

    /**
     * 审批记录Service
     */
    @Resource
    private IBizApprovalRecordService iBizApprovalRecordService;

    /**
     * 用户Mapper
     */
    @Resource
    private SysUserMapper sysUserMapper;

    /**
     * 消息推送
     */
    @Resource
    private WebSocketServer webSocketServer;

    /**
     * 员工Mapper
     */
    @Resource
    private BizStaffMapper staffMapper;

    /**
     * 表记录Mapper
     */
    @Resource
    private ISyTableRecordTService iSyTableRecordTService;

    /**
     * 查询离职申请
     * 
     * @param id 离职申请主键
     * @return 离职申请
     */
    @Override
    public OaDimission selectOaDimissionById(Long id)
    {
        return oaDimissionMapper.selectOaDimissionById(id);
    }

    /**
     * 查询离职申请列表
     * 
     * @param oaDimission 离职申请
     * @return 离职申请
     */
    @Override
    public List<OaDimission> selectOaDimissionList(OaDimission oaDimission)
    {
        return oaDimissionMapper.selectOaDimissionList(oaDimission);
    }

    /**
     * 新增离职申请
     * 
     * @param oaDimission 离职申请
     * @return 结果
     */
    @Override
    public AjaxResult insertOaDimission(OaDimission oaDimission)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请先登录");
        }
        // 判断是否再提交
        if (StringUtils.isNotBlank(oaDimission.getSerialNum())) {
            oaDimission.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaDimission.setUpdateBy(loginUser.getUsername());
            // 修改离职单，审批记录表，抄送
            return resubmitReimburse(oaDimission, loginUser);
        } else {
            // 获取流水单号
            String serialNum = iBizSerialNumTService.generateSerialNum("LZSQ");
            oaDimission.setSerialNum(serialNum);
            oaDimission.setBusinessStatus(Constants.APPROVE);
            oaDimissionMapper.insertOaDimission(oaDimission);
            iSyTableRecordTService.saveEntityAndTable(oaDimission,serialNum);
            // 插入审批记录表
            return setApprovalRecord(oaDimission, loginUser);
        }
    }
    /**
     * 重提交：修改表单，审批记录表，抄送
     * @param oaDimission
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult resubmitReimburse(OaDimission oaDimission, LoginUser loginUser) {
        //修改报销单
        oaDimissionMapper.updateOaDimission(oaDimission);
        //删除审批记录
        bizApprovalRecordMapper.deleteBizApprovalRecordBySerialNum(oaDimission.getSerialNum());
        // 删除抄送
        bizCopyMapper.deleteBizCopyMapperBySerialNum(oaDimission.getSerialNum());

        //新增审批及抄送
        return setApprovalRecord(oaDimission,loginUser);
    }

    /**
     * 插入审批记录表
     *
     * @param oaDimission
     */
    @Transactional(rollbackFor = Exception.class)
    AjaxResult setApprovalRecord(OaDimission oaDimission, LoginUser loginUser) {
        List<BizApprovalRecord> bizApprovalRecords;
        //是否使用模板
        String typeStatus = oaDimission.getTypeStatus();
        if ("0".equals(typeStatus)){
            //使用模板
            bizApprovalRecords= iBizApprovalRecordService.approvalTemplate(loginUser, oaDimission.getSerialNum(),"离职");
        }else{
            //不使用模板，自定义
            bizApprovalRecords = addApprovalRecord(oaDimission, loginUser);
        }
        bizApprovalRecordMapper.insertBatchBizApprovalRecord(bizApprovalRecords);

        // 增加抄送人
        addCopyPeople(oaDimission);

        // 推送消息
        List<BizApprovalRecord> messageList = bizApprovalRecords.stream()
                .filter(a -> a.getSequence() == 2)
                .collect(Collectors.toList());
        sendMessage(messageList.get(0).getApproverId(), messageList.get(0).getApproverName(), oaDimission);
        return new AjaxResult(HttpStatus.SUCCESS, "新增入职申请审批记录成功");
    }

    /**
     * 推送消息到前端
     * @param userId
     * @param userName
     * @param oaDimission
     */
    private void sendMessage(Long userId, String userName, OaDimission oaDimission) {
        try {
            //发送消息
            Message message = new Message();
            message.setFromId(oaDimission.getApplyUserId());
            message.setFromName(oaDimission.getApplyUserName());
            message.setNextNodeId(userId);
            message.setNextNodeName(userName);
            message.setStatus(Constants.COMPLETED);
            message.setSerialNum(oaDimission.getSerialNum());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("新增入职申请推送失败",e);
        }
    }



    /**
     * 自定义，添加审批记录
     * @return
     */
    public List<BizApprovalRecord> addApprovalRecord(OaDimission oaDimission, LoginUser loginUser){
        List<BizApprovalRecord> bizApprovalRecords = new ArrayList<>();
        int sequence = 1;
        // 保存发起人
        BizApprovalRecord initiatorRecord = createApprovalRecord(oaDimission, null, loginUser);
        initiatorRecord.setSequence(sequence);
        initiatorRecord.setSerialNum(oaDimission.getSerialNum());
        initiatorRecord.setApprovalStatus(Constants.COMPLETED);
        initiatorRecord.setTypeOperation(Constants.AGREE);
        initiatorRecord.setBusinessStatus(Constants.APPROVE);
        bizApprovalRecords.add(initiatorRecord);

        // 字符串分割，并把String[]转换为list(传入了一个字符串类型的数据）
        if (StringUtils.isEmpty(oaDimission.getApprover())) {
            throw new BaseException("请选审批人");
        }
        String[] approvers = oaDimission.getApprover().split(",");
        List<Long> idList = Arrays.stream(approvers).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        // 获取详细审批人信息
        List<SysUser> sysUserList = sysUserMapper.selectUserByUserIds(idList);
        if (idList.size() != sysUserList.size()) {
            throw new BaseException("新增入职申请审批人有误");
        }
        // 根据职位级别降级排序
        sysUserList.sort(Comparator.comparingLong(SysUser::getPositionLevel).reversed());

        // 增加审批记录
        if (!CollectionUtils.isEmpty(sysUserList)) {
            for (int i = 0; i < sysUserList.size(); i++) {
                SysUser sysUser = sysUserMapper.selectUserById(sysUserList.get(i).getUserId());
                if (Objects.isNull(sysUser)){
                    throw new BaseException("新增入职申请审批人信息有误");
                }
                BizApprovalRecord approvalRecord = createApprovalRecord(oaDimission, sysUser, null);
                if (i == 0) {
                    approvalRecord.setApprovalStatus(Constants.APPROVE);
                } else {
                    approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
                }
                sequence++;
                approvalRecord.setSequence(sequence);
                bizApprovalRecords.add(approvalRecord);
            }
        }
        return bizApprovalRecords;
    }

    /**
     * 添加抄送人
     * @param oaDimission
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopyPeople(OaDimission oaDimission) {
        if (StringUtils.isNoneBlank(oaDimission.getCopyerId())){
            //字符串分割，并把String[]转换为list，（抄送人id）
            String[] copyerIds = oaDimission.getCopyerId().split(",");
            List<String> copyerIdList = Arrays.stream(copyerIds).collect(Collectors.toList()) ;
            //抄送记录表
            if(!CollectionUtils.isEmpty(copyerIdList)){
                copyerIdList.forEach(id->{
                    BizCopy bizCopy = new BizCopy();
                    SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(id));
                    bizCopy.setApplicationId(oaDimission.getId());
                    bizCopy.setCopyerId(sysUser.getUserId());
                    bizCopy.setCopyerName(sysUser.getUserName());
                    bizCopy.setPositionLevel(sysUser.getPositionLevel());
                    bizCopy.setUserId(oaDimission.getApplyUserId());
                    bizCopy.setUsername(oaDimission.getApplyUserName());
                    bizCopy.setSerialNum(oaDimission.getSerialNum());
                    bizCopy.setCopyerStatus("0");
                    bizCopy.setCreateTime(DateUtils.getNowDate());
                    bizCopyMapper.insertBizCopy(bizCopy);
                });
            }
        }
    }

    /**
     * 设置审批记录信息
     *
     * @param oaDimission
     * @param sysUser
     * @return
     */
    public BizApprovalRecord createApprovalRecord(OaDimission oaDimission, SysUser sysUser, LoginUser loginUser) {
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        if (null != sysUser) {
            bizApprovalRecord.setApproverId(sysUser.getUserId());
            bizApprovalRecord.setApproverName(sysUser.getUserName());
            bizApprovalRecord.setPositionLevel(sysUser.getPositionLevel());
        }
        if (null != loginUser) {
            bizApprovalRecord.setApproverId(loginUser.getUserId());
            bizApprovalRecord.setApproverName(loginUser.getUsername());
        }
        bizApprovalRecord.setSerialNum(oaDimission.getSerialNum());
        bizApprovalRecord.setApplicationId(oaDimission.getId());
        bizApprovalRecord.setUserId(oaDimission.getApplyUserId());
        bizApprovalRecord.setUsername(oaDimission.getApproverName());
        bizApprovalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        bizApprovalRecord.setUpdateBy(oaDimission.getApplyUserName());
        bizApprovalRecord.setCreateBy(oaDimission.getApplyUserName());
        bizApprovalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return bizApprovalRecord;
    }

    /**
     * 修改离职申请
     * 
     * @param oaDimission 离职申请
     * @return 结果
     */
    @Override
    public int updateOaDimission(OaDimission oaDimission)
    {
        oaDimission.setUpdateTime(DateUtils.getNowDate());
        return oaDimissionMapper.updateOaDimission(oaDimission);
    }

    /**
     * 批量删除离职申请
     * 
     * @param ids 需要删除的离职申请主键
     * @return 结果
     */
    @Override
    public int deleteOaDimissionByIds(Long[] ids)
    {
        return oaDimissionMapper.deleteOaDimissionByIds(ids);
    }

    /**
     * 删除离职申请信息
     * 
     * @param id 离职申请主键
     * @return 结果
     */
    @Override
    public int deleteOaDimissionById(Long id)
    {
        return oaDimissionMapper.deleteOaDimissionById(id);
    }

    /**
     * 修改员工状态
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateStaffStatus() {
        //获取当前时间
        LocalDate now = LocalDate.now();
        LOGGER.info("当前时间："+now);
        //获取昨日离职人员
        OaDimission oaDimission = new OaDimission();
        oaDimission.setApplyDimissionDate(now.minusDays(1L));
        oaDimission.setBusinessStatus(Constants.COMPLETED);
        List<OaDimission> oaDimissionList = oaDimissionMapper.selectOaDimissionList(oaDimission);
        if (CollectionUtils.isEmpty(oaDimissionList)){
            return AjaxResult.success(0);
        }
        //修改员工状态为离职
        for (OaDimission dimission : oaDimissionList) {
            BizStaff bizStaff = new BizStaff();
            bizStaff.setId(dimission.getStaffId());
            bizStaff.setStatus("3");
            bizStaff.setLeaveDate(dimission.getApplyDimissionDate());
            staffMapper.updateBizStaff(bizStaff);
        }
        return AjaxResult.success(oaDimissionList.size());
    }
}
